<?php
declare(strict_types=1);

class Model
{
    private array $attributes;
    private object $database;
    private string $query_condition = '';
    private string $field = '*';
    protected string $table_name = '';
    public function __construct()
    {
        $this->database = Database::getInstance();
    }
    public function __call($name, $arguments)
    {
        echo "Control Function $name not found";
    }
    /**
     * @param $column
     * @param $value
     * @return $this
     */
    public function set($column, $value)
    {
        $this->attributes[$column] = "'" . $value ."'";
        return $this;
    }
    /**
     * @param $data
     * @return $this
     */
    public function setArr($data)
    {
        foreach($data as $column => $value){
            $this->attributes[$column] = "'" . $value ."'";
        }
        return $this;
    }
    /**
     * @param $column
     * @param $condition
     * @param $target
     * @return $this
     */
    public function where($column, $condition, $target = '')
    {
        if($target == ''){
            $target = $condition;
            $condition = '=';
        }
        if(empty($this->query_condition)){
            $this->query_condition = " where " . $column . " " . $condition . " " . $target;
        }else{
            $this->query_condition .= " and " . $column . " " . $condition . " " . $target;
        }
        return $this;
    }
    /**
     * @param $limit
     * @param int $offset
     * @return $this
     */
    public function limit($limit, $offset = 0)
    {
        $limit = $offset ? "$offset,$limit" : $limit;
        $this->query_condition .= " limit $limit";
        return $this;
    }
    public function field($field)
    {
        $this->field = $field;
        return $this;
    }
    /**
     * @param string $order
     * @return $this
     */
    public function orderBy($order)
    {
        $this->query_condition .= " Order By $order";
        return $this;
    }
    public function create()
    {
        $column_str = implode(',',array_keys($this->attributes));
        $value_str = implode(',',$this->attributes);
        $sql = "INSERT INTO $this->table_name " . "($column_str)" . " VALUES " . "($value_str)";
        $stmt = $this->database->prepare($sql);
        $stmt->execute();
        return $this->database->lastInsertId();
    }
    public function count($column = 'id')
    {
        $sql = "select COUNT(`$column`) from $this->table_name" . $this->query_condition;
        $stmt = $this->database->prepare($sql);
        $stmt->execute();
        return intval($stmt->fetchColumn());
    }
    public function select()
    {
        $sql = "select $this->field from $this->table_name" . $this->query_condition;
        $stmt = $this->database->prepare($sql);
        $stmt->execute();
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
    public function delete()
    {
        $sql = "DELETE FROM $this->table_name" . $this->query_condition;
        $stmt = $this->database->prepare($sql);
        $stmt->execute();
        return $stmt->rowCount();
    }
    public function update()
    {
        $set = '';
        foreach($this->attributes as $key=>$attribute){
            $set .= "$key = $attribute,";
        }
        $set = substr($set,0,-1);
        $sql = "update $this->table_name set $set" . $this->query_condition;
        $stmt = $this->database->prepare($sql);
        $stmt->execute();
        return $stmt->rowCount();
    }
    public function fetch()
    {
        $res = $this->limit(1)->select();
        return $res[0];
    }
    public function value($column = 'id')
    {
        $sql = "select `" . $column . "` from $this->table_name " . $this->query_condition . " limit 1";
        $stmt = $this->database->prepare($sql);
        $stmt->execute();
        return $stmt->fetchColumn();
    }
    //事务
    public function beginTransaction()
    {
        $this->database->beginTransaction();
    }
    //提交
    public function commit()
    {
        $this->database->commit();
    }
    //回滚
    public function rollback()
    {
        $this->database->rollBack();
    }
    /*
     * $sql
     */
    public function execute_sql($sql)
    {
        $stmt = $this->database->prepare($sql);
        $stmt->execute();
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
}